Ethan,没问题!在 Java 开发(尤其是像你现在研究的 Redis、微服务、RPC 通信)中,序列化是绕不开的核心。
简单来说,序列化就是把 Java 对象变成“二进制流”或“文本”,以便在网络传输或存入磁盘;反序列化则是把这些流变回 Java 对象。
我帮你从“原生”到“主流开源”梳理了一遍,你可以根据使用场景来选:
1. Java 原生序列化 (Serializable)
这是最基础的方法,类只需要实现 java.io.Serializable 接口。
- 实现方式:使用
ObjectOutputStream和ObjectInputStream。 - 优点:自带,无需额外依赖。
- 缺点(非常致命):
- 性能差:产生的码流非常大。
- 安全性极低:容易受到反序列化攻击(这也是为什么现代框架都在弃用它)。
- 不支持跨语言:只能 Java 连 Java。
2. JSON 序列化 (目前最主流)
把对象转成 JSON 字符串。这是你目前在 Redis 配置中使用的方案。
Jackson (Spring Boot 默认)
特点:功能极其强大,配置灵活,生态最好。
适用场景:Spring Boot 内部、Web 开发、Redis 存储。
代码参考:
Java
ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(user); // 序列化 User user = mapper.readValue(json, User.class); // 反序列化
FastJSON / FastJSON2 (阿里出品)
特点:速度极快,国内公司用得非常多。
注意:历史版本安全漏洞较多,建议只用最新的 FastJSON2。
java// 将对象转为 JSON 字符串 String jsonString = JSON.toJSONString(user); // 将 JSON 字符串转回对象 User user = JSON.parseObject(json, User.class);
3. 二进制序列化框架 (高性能首选)
如果你在做高并发、高性能的分布式系统(比如 Dubbo 或大流量 RPC),JSON 的体积就太大了,这时需要专业的二进制序列化。
Protobuf (Google 出品)
- 特点:体积小到极致,速度极快。
- 原理:基于
.proto文件定义数据结构,然后自动生成代码。 - 缺点:使用繁琐,需要预先定义结构,不能像 JSON 那样随便写。
Kryo (追求速度的 Java 专属)
- 特点:在 Java 内部序列化中,速度几乎是最快的,体积也非常小。
- 注意:它不跨语言,只能用于 Java 项目之间。
Hessian
- 特点:老牌经典,由于其稳定性和良好的跨语言支持,常作为 Dubbo 等框架的默认序列化协议。
4. 总结与选择指南
为了让你更清晰,我把它们放在一起对比:
| 方案 | 速度 | 压缩体积 | 跨语言 | 易用性 | 推荐场景 |
|---|---|---|---|---|---|
| Java 原生 | 极慢 | 极大 | 否 | 高 | 不要用 |
| Jackson | 中等 | 中 | 是 | 极高 | Spring Boot/Web/Redis 首选 |
| FastJSON2 | 快 | 中 | 是 | 极高 | 国内业务开发 |
| Protobuf | 极快 | 极小 | 是 | 低 | 高性能微服务、即时通讯 |
| Kryo | 极快 | 小 | 否 | 中 | Java 高性能计算、内部缓存 |
💡 给 Ethan 的小建议
由于你正在学习 Redis 和 Spring Boot 3.x,你只需要精通 Jackson 就足够应付 90% 的场景了。
- 对于简单的 Key-Value:直接用
StringRedisTemplate,手动把对象转成 JSON 字符串存进去。 - 对于复杂的对象存储:使用你在
redisTemplate里的那种GenericJackson2JsonRedisSerializer配置(或者最新的RedisSerializer.json())。
5. 手动配置的RedisTemplate和StringRedisTemplate选择
这是一个非常深刻的工程实践问题。简单直接的回答是:会用,而且在高并发或跨语言的场景下,StringRedisTemplate 反而是主角。
虽然你配置好了全自动的 RedisTemplate<String, Object>,但它们两人在项目里是**“互补”**关系,而不是“替代”关系。
5.1 核心分水岭:@class 属性
当你使用 GenericJackson2JsonRedisSerializer 配置 RedisTemplate 时,它为了实现“全自动反序列化”,会在 JSON 里塞进一个 @class 字段:
RedisTemplate存的结果:JSON
{ "@class": "com.hmdp.entity.Shop", "id": 1, "name": "Ethan的咖啡店", "expiredTime": "2026-04-05 21:00:00" }StringRedisTemplate存的结果(配合手动转 JSON):JSON
{ "id": 1, "name": "Ethan的咖啡店", "expiredTime": "2026-04-05 21:00:00" }
为什么这个差别很重要?
- 跨语言兼容性:如果以后你的项目引入了 Python 或 Go 写的微服务,它们读取 Redis 时看到
@class会一脸懵逼,因为那是 Java 特有的类路径。 - 存储开销:在高并发场景下,成千上万个 Key 都带上长长的包名类名,会浪费不少内存空间。
- 耦合度:如果以后你重构了代码,把
Shop类改了包名,旧缓存里的@class路径就失效了,反序列化会直接崩掉。
5.2 什么时候选谁?(避坑指南)
我们可以根据业务需求来做选择:
✅ 推荐使用 RedisTemplate<String, Object> 的场景:
- 快速开发:内部小项目,或者不考虑跨语言,只想写代码快,不想每次都手动
toBean。 - 深度绑定 Java 的对象:比如存取复杂的 Session、权限信息等,这些数据通常只在 Java 内部流动。
✅ 推荐使用 StringRedisTemplate 的场景:
- 高并发/大体量数据:为了节省内存,只存纯净的 JSON。
- 简单计数/标识:如
incr自增(点赞数)、验证码、分布式锁。 - 跨系统共享数据:比如你要存一个数据给前端 Node.js 渲染或者给 Python 脚本分析。
- 黑马点评/苍穹外卖等教学项目:这些项目后期通常会教你如何手动处理 JSON,以模拟真实大厂对性能和兼容性的极致要求。
5.3 黄金组合建议
在实际的生产架构中,Ethan,你可以参考这个配置比例:
- 80% 的情况用
StringRedisTemplate:- 配合我们在
JacksonConfig里注入的objectMapper手动转字符串。 - 这样虽然多写一行代码,但换来了极高的兼容性和透明的数据格式。
- 配合我们在
- 20% 的情况用
RedisTemplate:- 用于存储一些结构极其复杂、且只有当前服务自己会用的临时对象。
5.4 总结
你配置的 RedisTemplate 是**“高级自动挡”,让你开得爽;而 StringRedisTemplate 是“手动挡”**,让你在复杂路况(跨语言、高并发)下有更强的掌控力。
在你的 writeCache 方法里,如果你现在已经把 JacksonConfig 配好了,我建议你尝试注入 ObjectMapper 并使用 StringRedisTemplate,这样你存进 Redis 的数据会非常漂亮且纯净。
目前在你的项目中,是否有其他部门或者其他语言编写的微服务需要读取你的 Redis 数据呢?